﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

using InfFront.UICore;

namespace InfFront.InfoViews.WPF
{
    /// <summary>
    /// Interaction logic for ProgressDialog.xaml
    /// </summary>
    public partial class ProgressDialog : Window
    {
        private static readonly DependencyProperty MainMessageProperty;
        private static readonly DependencyProperty ProgressMessageProperty;
        private static readonly DependencyProperty ProgressProperty;

        private IExecutionControl exec;
        private Cursor prevOverrideCursor;
        private System.Windows.Threading.DispatcherTimer updateTimer;

        static ProgressDialog()
        {
            MainMessageProperty = DependencyProperty.Register("MainMessage", typeof(string), typeof(ProgressDialog));
            ProgressMessageProperty = DependencyProperty.Register("ProgressMessage", typeof(string), typeof(ProgressDialog));
            ProgressProperty = DependencyProperty.Register("Progress", typeof(double), typeof(ProgressDialog));
        }

        public ProgressDialog(IExecutionControl exec, object dataContext)
        {
            this.DataContext = dataContext;
            this.IsFinished = false;

            this.exec = exec;
            if (exec != null)
                MainMessage = exec.GetExecutionMessage();
            else
            {
                MainMessage = "Please wait...";
                btnCancel.Visibility = Visibility.Hidden;
            }

            InitializeComponent();
        }

        public bool IsFinished { get; set; }

        public void Start()
        {
            if (updateTimer == null)
            {
                updateTimer = new System.Windows.Threading.DispatcherTimer();
                updateTimer.Interval = new TimeSpan(0, 0, 0, 0, 500);
                updateTimer.Tick += new EventHandler(updateTimer_Tick);
            }

            Resume();
        }

        public void Pause()
        {
            updateTimer.IsEnabled = false;
            Mouse.OverrideCursor = prevOverrideCursor;
            if (IsVisible)
                Hide();
        }

        public void Resume()
        {
            //Show(); ?
            prevOverrideCursor = Mouse.OverrideCursor;
            Mouse.OverrideCursor = Cursors.Wait;
            updateTimer.IsEnabled = true;
        }

        internal void OnRunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            IsFinished = true;
            Pause();
        }

        public string MainMessage
        {
            get { return (string)GetValue(MainMessageProperty); }
            set { SetValue(MainMessageProperty, value); }
        }

        public string ProgressMessage
        {
            get { return (string)GetValue(ProgressMessageProperty); }
            set { SetValue(ProgressMessageProperty, value); }
        }

        public double Progress
        {
            get { return (double)GetValue(ProgressProperty); }
            set { SetValue(ProgressProperty, value); }
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Debug.Assert(exec != null);
            exec.Cancel();
            MainMessage = "Cancelling...";
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (exec != null)
            {
                btnCancel_Click(sender, null);
                e.Cancel = true;
            }
        }

        void updateTimer_Tick(object sender, EventArgs e)
        {
            if (Visibility != Visibility.Visible)
            {
                Delegate d = new Action(delegate() 
                    {
                        Mouse.OverrideCursor = prevOverrideCursor;
                        ShowDialog(); 
                    });
                Dispatcher.BeginInvoke(d, null);
            }

            if (exec == null)
                return;

            float progress = -1;
            string pMessage = string.Empty;
            exec.GetExecutionProgressAndMessage(out progress, out pMessage);
            if (progress > 0)
            {
                Progress = progress;
                ProgressMessage = pMessage;
                progressPanel.Visibility = Visibility.Visible;
            }
        }
    }
}
